package vsqlbuilder.gui;

import static vsqlbuilder.gui.MainController.ARROW;
import static vsqlbuilder.gui.MainController.JOIN;

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;

import javax.swing.AbstractButton;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JToggleButton;
import javax.swing.JToolBar;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingConstants;

import vsqlbuilder.Utils;

public class MainView extends JFrame {
	static final long serialVersionUID = 0L; //TODO [low]: temporary fix, must be change to correct one
	
	private MainController Controller;
	private TablesTree tablestree;
	private ConnectionManager ConnectionWindow;
	
	private JMenuItem ItemNewConn, ItemCloseConn, ItemExecute;
	private AbstractButton openButton, closeButton, createButton, executeButton;
	private Tabs tabbedPane;
	
	public MainView(){
		this.setTitle("Visual SQL Builder 0.3, isn't ready for final user use, please contribute to project & report bugs [ A lot :) ] on tracker at sourceforge");
		//Set the window initial Size & default close operation
		this.setVisible(false);
		Dimension fullscreen = Toolkit.getDefaultToolkit().getScreenSize();
		fullscreen.width=fullscreen.width-100;
		fullscreen.height=fullscreen.height-100;
		this.setBounds(50,50,fullscreen.width,fullscreen.height);
		getContentPane().setPreferredSize(fullscreen);
		
	    this.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);

	    //Initialize Logic & Graphic Model of Application
	    Controller = new MainController();
	    Controller.registerModel(new Dimension(1000,800));
	    
	    //Create & Initialize Main Window Objects & add to window
	    Container guiobjects = getContentPane();
	    guiobjects.setLayout(new BorderLayout());
	    
	    StatusBar statusBar = new StatusBar();
	    guiobjects.add(getToolBar(), BorderLayout.NORTH);
	    guiobjects.add(statusBar, BorderLayout.SOUTH);
	   	
	   	
	   	tablestree = new TablesTree(Controller);
	   	Controller.registerTree(tablestree);
	   	 	
	    JScrollPane treeView = new JScrollPane(tablestree);
	    JSplitPane splitPaneHorizontal = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
	    splitPaneHorizontal.setTopComponent(treeView);
	        
		JScrollPane ModelScroll = new JScrollPane(Controller.Model.view, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
	    
	    splitPaneHorizontal.setBottomComponent(ModelScroll); 
        splitPaneHorizontal.setDividerLocation(200); 
	   
        JSplitPane splitPaneVertical = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
        splitPaneVertical.setDividerLocation(400);
        splitPaneVertical.setTopComponent(splitPaneHorizontal);
	   	
        tabbedPane = new Tabs(MainView.this.Controller);
        splitPaneVertical.setBottomComponent(tabbedPane);
        guiobjects.add(splitPaneVertical, BorderLayout.CENTER);

       
        this.pack();
		//this.setVisible(true);

	   	this.setJMenuBar(this.returnMenu());
	   	
	   	
		//TODO [low]: Font Metrics search another better way of to do this
		Controller.registerMetrics(); //Bug Fix [Bug #1], Font Metrics

		//Repaint the Model for
		Controller.repaintModel();
		
		//Show Main ASKING FOR HELP Dialog to User
		JOptionPane.showMessageDialog(this, "This is a pre-alpha release of this application, isn't ready for final user use. \n\n\nBut you can help to finish this application by supporting our project, please visit: \n        http://vsqlbuilder.sourceforge.net \n            (List of possible contributions: \n             use ours forums, reports bugs, ask for new functionalities or even \n            download our SVN version fix something and send us a patch) \nOr simply write us for tasks to do, at:\n        http://sourceforge.net/sendmessage.php?touser=1420341\n\nEveryone is Welcome,\nEvery Contribution to this Project is Important: No Matter How Large or Small\n\nNote: if have any trouble when executing a query please use jre>=1.6");


	}

	
	//Override function 
    protected void processWindowEvent(WindowEvent event) {

    	if (event.getID() == WindowEvent.WINDOW_CLOSING) {
    	    this.Controller.exitApplication();
    	    //TODO [low]: do try catch to exit
    	}
    	super.processWindowEvent(event);
        }
    
    private JMenuBar returnMenu(){

    	JMenuBar menu = new JMenuBar();

    	menu.add(getFileMenu());

    	menu.add(getHelpMenu());

    	return menu;
    }
    
    private JMenu getFileMenu(){
    	JMenu menu = new JMenu("File");

    	//Items
    	ItemNewConn = new JMenuItem("New Connection");
    	ItemCloseConn = new JMenuItem("Close Connection");
    	    	
    	
    	
    	//Item #1
    	ItemNewConn.addActionListener(new ActionListener() {
    	    public void actionPerformed(ActionEvent event) {
    	    	MainView.this.createConnection();
    	    }
    	});
    	menu.add(ItemNewConn);
    	
    	//Item #2
    	ItemCloseConn.setEnabled(false);
    	ItemCloseConn.addActionListener(new ActionListener() {
    	    public void actionPerformed(ActionEvent event) {
    	    	MainView.this.closeConnection();
    	    }
    	});
    	menu.add(ItemCloseConn);
    	
    	ItemExecute = new JMenuItem("Execute SQL");
    	ItemExecute.setEnabled(true);
    	ItemExecute.addActionListener(new ActionListener() {
    	    public void actionPerformed(ActionEvent event) {
    	    	String sql=MainView.this.Controller.Model.QueryStatment.GenerateSentence();
    	    	MainView.this.tabbedPane.panel1.setGeneratedSQL(sql);
    	    	SqlExecute ExecutionWindow = new SqlExecute(MainView.this, MainView.this.Controller.Logic.DatabaseConnection, MainView.this.Controller.Model.QueryStatment);
    	    	 MainView.this.Controller.Logic.DatabaseConnection.closeConnection(); //TODO [low]: this must be done here because lack of destructor in SqlExecute code, search if there are better solutions
    	    	ExecutionWindow.setVisible(true);
    	    	
    	    }
    	});    	
    	ItemExecute.setEnabled(false);
    	menu.add(ItemExecute);
    	
    	menu.addSeparator();

    	//Item #3
    	JMenuItem Item = new JMenuItem("Quit");
    	Item.addActionListener(new ActionListener() {
    	    public void actionPerformed(ActionEvent event) {
    		Controller.exitApplication();
    	    }
    	});
    	menu.add(Item);
    	
    	return menu;
    }
	
    private JMenu getHelpMenu() {

    	JMenu menu = new JMenu("Help");
    	JMenuItem Item = new JMenuItem("About");
    	Item.addActionListener(new ActionListener() {

    	    public void actionPerformed(ActionEvent evt) {
    	    	SplashScreen.splash(null); //TODO [low]: verify null can be here without consequences 
    	    }
    	});
    	menu.add(Item);
    	return menu;
        }
    
    
    private JToolBar getToolBar() {
		
    	JToolBar toolBar = new JToolBar();
    	toolBar.setOrientation(SwingConstants.HORIZONTAL);
    	toolBar.setFloatable(false);

    	ToolBarButtonGroup group = new ToolBarButtonGroup(this);
    	
    	//Open Connection Button
    	openButton = createToolBarButtonNomal(group,
    			ARROW, "toolbar/Open.gif",
    			"Open Database Connection", new Cursor(Cursor.DEFAULT_CURSOR));
    	toolBar.add(openButton);    	
    	openButton.addActionListener(new ActionListener() {
    		public void actionPerformed(ActionEvent event) {
    			MainView.this.createConnection();
			}
    	});
    	    	
    	toolBar.addSeparator(new Dimension(1,10));
    	
    	//Close Connection Button
    	closeButton = createToolBarButtonNomal(group,
    			ARROW, "toolbar/Close.gif",
    			"Close Database Connection", new Cursor(Cursor.DEFAULT_CURSOR));
    	toolBar.add(closeButton);
    	closeButton.setEnabled(false);
    	closeButton.addActionListener(new ActionListener() {
    		public void actionPerformed(ActionEvent event) {
    			MainView.this.closeConnection();
			}
    	});
    	
    	toolBar.addSeparator(new Dimension(1,10));
    	
    	//Create SQL Statement Button
    	createButton = createToolBarButtonNomal(group,
    			ARROW, "toolbar/Create.gif",
    			"Create But Not execute SQL Statement", new Cursor(Cursor.DEFAULT_CURSOR));
    	toolBar.add(createButton);
    	createButton.setEnabled(false);
    	createButton.addActionListener(new ActionListener() {
    		public void actionPerformed(ActionEvent event) {
    	    	String sql=MainView.this.Controller.Model.QueryStatment.GenerateSentence();
    	    	MainView.this.tabbedPane.setSelectedIndex(0);
    	    	MainView.this.tabbedPane.panel1.setGeneratedSQL(sql);
			}
    	}); 
    	
    	toolBar.addSeparator(new Dimension(1,10));
    	//Execute SQL Button
    	executeButton = createToolBarButtonNomal(group,
    			ARROW, "toolbar/Execute.gif",
    			"Execute the SQL Genereted Automatically", new Cursor(Cursor.DEFAULT_CURSOR));
    	toolBar.add(executeButton);
    	executeButton.setEnabled(false);
    	executeButton.addActionListener(new ActionListener() {
    		public void actionPerformed(ActionEvent event) {
    	    	String sql=MainView.this.Controller.Model.QueryStatment.GenerateSentence();
    	    	MainView.this.tabbedPane.panel1.setGeneratedSQL(sql);
    	    	SqlExecute ExecutionWindow = new SqlExecute(MainView.this, MainView.this.Controller.Logic.DatabaseConnection, MainView.this.Controller.Model.QueryStatment);
    	    	MainView.this.Controller.Logic.DatabaseConnection.closeConnection(); //TODO [low]: this must be done here because lack of destructor in SqlExecute code, search if there are better solutions
    	    	MainView.this.tabbedPane.setSelectedIndex(0);
    	    	ExecutionWindow.setVisible(true);
			}
    	});
    	
    	toolBar.addSeparator(new Dimension(50,10));
    	
    	//Arrow Button
    	AbstractButton pointButton = createToolBarButton(group,
    			ARROW, "toolbar/Arrow.gif",
    			"Move tables & Select columns for Query", new Cursor(Cursor.DEFAULT_CURSOR));
    	toolBar.add(pointButton);
    	pointButton.setSelected(true);
    	
  	   	toolBar.addSeparator();
  	   	
    	//Join Button
    	AbstractButton joinButton =	createToolBarButton(group, JOIN,
    			"toolbar/Join.gif", "Join Tables using column [NO implemented YET]",
    			"cursors/Join.gif", 0, 0);
    	toolBar.add(joinButton);
    	
    	
    	
    	Controller.registerToolBarGroup(group);
   	   	return toolBar;
    }
    
    private static JToggleButton createToolBarButton(
    	    ToolBarButtonGroup buttonGroup, int mnemonic,
    	    String buttonImagePath, String tooltipKey, Cursor cursor) {

    	JToggleButton button = new JToggleButton();
    	button.setIcon(Utils.getImageIcon(buttonImagePath));
    	button.setFocusable(false);
    	button.setMnemonic(mnemonic);
    	button.setToolTipText(tooltipKey);
    	buttonGroup.add(button, cursor);

    	return button;
        }
    
    private static JToggleButton createToolBarButton(
    	    ToolBarButtonGroup buttonGroup, int mnemonic,
    	    String buttonImagePath, String tooltipKey, String cursorImagePath,
    	    int x, int y) {

    	Toolkit toolkit = Toolkit.getDefaultToolkit();
    	Cursor cursor = toolkit.createCustomCursor(Utils.getImageIcon(cursorImagePath).getImage(), new Point(x, y), cursorImagePath);

    	return createToolBarButton(buttonGroup, mnemonic, buttonImagePath,
    		tooltipKey, cursor);
        }
    
    private static JButton createToolBarButtonNomal(
    	    ToolBarButtonGroup buttonGroup, int mnemonic,
    	    String buttonImagePath, String tooltipKey, Cursor cursor) {

    	JButton button = new JButton();
    	button.setIcon(Utils.getImageIcon(buttonImagePath));
    	button.setFocusable(false);
    	button.setMnemonic(mnemonic);
    	button.setToolTipText(tooltipKey);
    	buttonGroup.add(button, cursor);

    	return button;
        }
    
    private void createConnection(){
    	if (ConnectionWindow!=null)
    		ConnectionWindow.setVisible(true);
    	else
    		ConnectionWindow = new ConnectionManager(null,Controller);

    	if(Controller.Logic.DatabaseConnection!=null){
        	if(Controller.Logic.DatabaseConnection.isOpenConnection())
        	{
        		tablestree.setEnabled(true);
        		ItemCloseConn.setEnabled(true);
        		ItemNewConn.setEnabled(false);
        		closeButton.setEnabled(true);
        		openButton.setEnabled(false);
        		ItemExecute.setEnabled(true);
        		executeButton.setEnabled(true);
        		createButton.setEnabled(true);
        		tabbedPane.panel2inside.mainButton.setEnabled(true);
        		}
        	else{
        		ItemCloseConn.setEnabled(false);
        		ItemNewConn.setEnabled(true);
        		closeButton.setEnabled(false);
        		openButton.setEnabled(true);
        		ItemExecute.setEnabled(false);
        		executeButton.setEnabled(false);
        		createButton.setEnabled(false);
        		tabbedPane.panel2inside.mainButton.setEnabled(false);
        		}
    	}
    }
    
    private void closeConnection(){
    	ConnectionWindow.cleanTextFields();
    	Controller.Logic.DatabaseConnection.closeConnection();
    	ItemNewConn.setEnabled(true);
		ItemCloseConn.setEnabled(false);
		openButton.setEnabled(true);
		closeButton.setEnabled(false);
		ItemExecute.setEnabled(false);
		executeButton.setEnabled(false);
		createButton.setEnabled(false);
		Controller.emptyTree();	
		tablestree.setEnabled(false);
		Controller.emptyDiagram();
		Controller.Model.view.repaint();
		tabbedPane.panel2inside.mainButton.setEnabled(false);
		tabbedPane.panel2inside.clearTabRestrictions();
    }
    
}
